package top.xtcoder.jdcbase.base.service;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.entity.Record;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.lang.Strings;
import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import cn.dev33.satoken.stp.StpUtil;
import top.xtcoder.jdcbase.base.common.Funs;
import top.xtcoder.jdcbase.base.core.Resp;
import top.xtcoder.jdcbase.base.core.UserLoginOpType;
import top.xtcoder.jdcbase.base.entity.base.AccountInfo;
import top.xtcoder.jdcbase.base.redis.PrRedisKey;
import top.xtcoder.jdcbase.base.redis.RedisCache;
import top.xtcoder.jdcbase.base.vo.auth.LoginResult;
import top.xtcoder.jdcbase.base.vo.auth.PhoneVrcodeLoginVo;
import top.xtcoder.jdcbase.base.vo.auth.PwdLoginVo;

@Service
public class AccountService {
	@Autowired
	private Dao dao;

	@Autowired
	private RedisCache redisCache;

	/**
	 * 密码登录
	 * @param table
	 * @param request
	 * @param dto
	 * @return
	 * @param <T>
	 * @throws Exception
	 */
	public <T extends AccountInfo> LoginResult pwdLogin(int type, Class<T> table,
		   HttpServletRequest request,
		   PwdLoginVo dto) throws Exception{
		String account=dto.getAccount();
		String pwd=dto.getPassword();
		String tableName = table.getAnnotation(Table.class).value();
		Cnd cnd = Cnd.where("isdelete", "=", 0)
			.and("account", "=", account);
		Record record = dao.fetch(tableName, cnd);
		if (record == null) {
			throw new Exception("用户不存在");
		}
		T userInfo =  record.toPojo(table);
		if (!Strings.equals(Funs.pwdEncry(pwd, userInfo.getSalt()), userInfo.getPassword())) {
			throw new Exception("密码错误");
		}
		if (userInfo.getState() == UserLoginOpType.LOCK.value()) {
			throw new Exception("帐号锁定, 不能登陆");
		}
		StpUtil.login(Funs.getSaLoginId(type, userInfo.getId()));
		LoginResult res = new LoginResult();
		res.setAccountInfo(userInfo);
		res.setTokenInfo(StpUtil.getTokenInfo());
		return res;
	}

	/**
	 * 手机号验证码登录
	 * @param table
	 * @param request
	 * @param dto
	 * @return
	 * @param <T>
	 * @throws Exception
	 */
	public <T extends AccountInfo> NutMap phoneVrcodeLogin(Class<T> table,
														   HttpServletRequest request,
														   PhoneVrcodeLoginVo dto) throws Exception{
		String account=dto.getAccount();
		String vrcode =dto.getVrcode();
		String storageVrcode = redisCache.getCacheObject(PrRedisKey.PB_PHONE_VRCODE(dto.getAccount()));
		if (!Strings.equals(vrcode, storageVrcode)) {
			throw new Exception("验证码输入错误");
		}

		String tableName = table.getAnnotation(Table.class).value();
		Cnd cnd = Cnd.where("isdelete", "=", 0)
				.and("account", "=", account);
		Record record = dao.fetch(tableName, cnd);
		if (record == null) {
			throw new Exception("用户不存在");
		}
		T userInfo =  record.toPojo(table);

		if (userInfo.getState() == UserLoginOpType.LOCK.value()) {
			throw new Exception("帐号锁定, 不能登陆");
		}


		return NutMap.NEW()
				.addv("userInfo", userInfo)
				.addv("tokenInfo", StpUtil.getTokenInfo());
	}

	/**
	 * 重设密码
	 * @param t
	 * @param oldPwd 旧密码(需md5加密)
	 * @param newPwd 新密码(需md5加密)
	 * @param id 用户id
	 * @param <T>
	 * @return
	 */
	public <T extends AccountInfo > Resp setPwd(Class<T> t, String oldPwd, String newPwd, String id){
		if(Strings.isBlank(id)) {
			return new Resp().error("参数不能空");
		}
		if(Strings.isBlank(oldPwd)) {
			return new Resp().error("旧密码不能空");
		}
		if(Strings.isBlank(newPwd)) {
			return new Resp().error("新密码不能空");
		}
		T data=dao.fetch(t,id);
		if(!Strings.equals(Funs.pwdEncry(oldPwd, data.getSalt()), data.getPassword())) {
			return new Resp().error("旧密码错误，请重新输入");
		}
		String salt = R.captchaChar(4);
		data.setSalt(salt);
		data.setPassword(Funs.pwdEncry(newPwd, salt));
		int n =  dao.update(data);
		return Resp.OBJ_O(n);
	}

	/**
	 * 重置密码
	 * @param t
	 * @param newPwd 新密码(需md5加密)
	 * @param id
	 * @param <T>
	 * @return
	 */
	public <T extends AccountInfo > Resp<T> resetPwd(Class<T> t,String newPwd,String id){
		if(Strings.isBlank(id)) {
			return new Resp().error("参数不能空");
		}
		if(Strings.isBlank(newPwd)) {
			return new Resp().error("新密码不能空");
		}
		T  data = dao.fetch(t, id);
		String salt = R.captchaChar(4);
		data.setSalt(salt);
		data.setPassword(Funs.pwdEncry(newPwd, salt));
		int n =  dao.update(data);
		if(n > 0) {
			return new Resp().ok("保存成功", data);
		}else {
			return new Resp().error("保存失败");
		}
	}
}
